package org.jim.core.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.*;
import org.jim.core.packets.pub.consts.Command;
import org.jim.core.packets.RespBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author WChao
 * 2017年4月16日 上午11:36:53
 */
public class JsonKit {
    private static Logger log = LoggerFactory.getLogger(JsonKit.class);

    private static String COMMAND = "command";

    private static SerializeConfig mapping = new SerializeConfig();

    static {
        mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
        mapping.put(java.sql.Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
        mapping.put(java.sql.Timestamp.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
        mapping.put(java.sql.Time.class, new SimpleDateFormatSerializer("HH:mm:ss"));
    }

    public static SerializeConfig put(Class<?> clazz, SerializeFilter filter) {
        mapping.addFilter(clazz, filter);
        return mapping;
    }

    public static SerializeConfig put(Class<?> clazz, ObjectSerializer serializer) {
        mapping.put(clazz, serializer);
        return mapping;
    }

    public static <T> T toBean(String jsonString, Class<T> tt) {
        try {
            if (StrUtil.isBlank(jsonString)) {
                return null;
            }

            T t = JSON.parseObject(jsonString, tt);
            return t;
        } catch (Throwable e) {
            log.error("json解析失败:\r\n{}", jsonString);
            throw new RuntimeException(e);
        }
    }

    public static <T> T toBean(byte[] bytes, Class<T> tt) {
        try {
            if (bytes == null) {
                return null;
            }

            T t = JSON.parseObject(bytes, tt);
            return t;
        } catch (Throwable e) {
            log.error("json解析失败:\r\n{}", bytes);
            throw new RuntimeException(e);
        }
    }

    public static String toFormatedJson(Object bean) {
        try {
            return JSON.toJSONString(bean, mapping, SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.PrettyFormat);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public static String toJSONEnumNoUsingName(Object bean) {
        int features = SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.WriteEnumUsingName, false);
        //增加了一个filter
        return JSONObject.toJSONString(bean, SerializeConfig.globalInstance, new SerializeFilter[]{new ValueFilter() {
            @Override
            public Object process(Object object, String name, Object value) {
                if (value instanceof Command) {
                    return ((Command) value).getNumber();
                }
                return value;
            }
        }}, null, features);
        //return JSONObject.toJSONString(bean,features);
    }


    public static String toJSONString(Object bean, SerializerFeature serializerFeature) {
        return JSONObject.toJSONString(bean, mapping, serializerFeature);
    }

    public static String toJSONString(Object bean) {
        try {
            return JSON.toJSONString(bean, mapping, SerializerFeature.DisableCircularReferenceDetect);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public static String toJSONString(Object bean, SerializeFilter serializeFilter) {
        try {
            if (serializeFilter != null) {
                return JSON.toJSONString(bean, mapping, serializeFilter, SerializerFeature.DisableCircularReferenceDetect);
            } else {
                return JSON.toJSONString(bean, mapping, SerializerFeature.DisableCircularReferenceDetect);
            }

        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] toJsonBytes(Object bean) {
        byte[] beanMap = bean2Map(bean, null);
        if (beanMap != null) return beanMap;
        return JSON.toJSONBytes(bean, mapping, SerializerFeature.DisableCircularReferenceDetect);
    }

    public static byte[] toJSONBytesEnumNoUsingName(Object bean) {
        int features = SerializerFeature.config(JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.WriteEnumUsingName, false);
        byte[] beanMap = bean2Map(bean, features);
        if (beanMap != null) return beanMap;
        return JSONObject.toJSONBytes(bean, features);
    }

    private static byte[] bean2Map(Object bean, Integer features) {
        if (bean instanceof RespBody) {
            Map<String, Object> beanMap = BeanUtil.beanToMap(bean);
            Command command = (Command) beanMap.get(COMMAND);
            beanMap.put(COMMAND, command.getNumber());
            return JSONObject.toJSONBytes(beanMap, features);
        }
        return null;
    }

    /**
     * 成指定类型集合;
     *
     * @param datas
     * @param clazz
     * @return
     */
    public static <T> List<T> toArray(List<String> datas, Class<T> clazz) {
        if (datas == null) {
            return null;
        }
        List<T> result = new ArrayList<T>();
        for (String obj : datas) {
            result.add(toBean(obj, clazz));
        }
        return result;
    }

}
